package mongox

import (
	"go.mongodb.org/mongo-driver/bson"
)

// SetOperation 用于构建MongoDB查询条件
type SetOperation[T int64 | string] struct {
	Values   []T          `json:"values,omitempty"`
	Relation RelationType `json:"relation,omitempty"`
}

// RelationType 定义集合关系类型
type RelationType string

const (
	IsSubsetOf             RelationType = "is_subset_of"               // values是目标集合(数据库字段)的子集
	IsNotSubsetOfTarget    RelationType = "is_not_subset_of_target"    // values不是目标集合(数据库字段)的子集
	IsProperSubsetOfTarget RelationType = "is_proper_subset_of_target" // values是目标集合(数据库字段)的真子集
	TargetIsProperSubsetOf RelationType = "target_is_proper_subset_of" // 目标集合(数据库字段)是values的真子集
	IsSupersetOf           RelationType = "is_superset_of"             // values是目标集合(数据库字段)的超集
	HasIntersection        RelationType = "has_intersection"           // values与目标集合(数据库字段)有交集
	NoIntersection         RelationType = "no_intersection"            // values与目标集合(数据库字段)无交集
	Equal                  RelationType = "equal"                      // values与目标集合(数据库字段)相等
)

// ToFilter 将SetOperation转换为MongoDB查询条件
func (s *SetOperation[T]) ToFilter(fieldName string) []bson.M {
	values := s.Values
	if len(values) == 0 {
		values = []T{}
	}

	switch s.Relation {
	case IsSubsetOf:
		// values是目标集合(数据库字段)的子集
		// 使用 $not 和 $elemMatch 确保查询数组中的每个元素都在数据库数组中
		return []bson.M{{fieldName: bson.M{"$not": bson.M{"$elemMatch": bson.M{"$nin": values}}}}}
	case IsNotSubsetOfTarget:
		// values 不是目标集合的子集
		// 意味着：存在至少一个 values 中的元素不在目标集合中
		return []bson.M{
			{fieldName: bson.M{"$not": bson.M{"$all": values}}},
		}
	case IsSupersetOf:
		// values是目标集合(数据库字段)的超集
		// 使用 $all 确保数据库中的数组包含所有给定的元素
		return []bson.M{{fieldName: bson.M{"$all": values}}}

	case IsProperSubsetOfTarget:
		// // values是目标集合(数据库字段)的真子集
		// return []bson.M{
		// 	{fieldName: bson.M{"$all": values}},
		// 	{"$expr": bson.M{"$gt": []interface{}{
		// 		bson.M{"$size": "$" + fieldName},
		// 		len(values),
		// 	}}},
		// }
		// values是目标集合(数据库字段)的真子集
		return []bson.M{
			// 确保字段存在且是数组
			{fieldName: bson.M{"$exists": true, "$type": "array"}},
			// 确保包含所有values中的元素
			{fieldName: bson.M{"$all": values}},
			// 确保目标集合大小大于values的大小
			{"$expr": bson.M{"$gt": []interface{}{
				bson.M{"$size": bson.M{"$ifNull": []interface{}{"$" + fieldName, []interface{}{}}}},
				len(values),
			}}},
		}
	case TargetIsProperSubsetOf:
		// 目标集合(数据库字段)是 values 的真子集
		return []bson.M{
			// 确保数据库中的数组的所有元素都在 values 中
			{fieldName: bson.M{"$not": bson.M{"$elemMatch": bson.M{"$nin": values}}}},
			// 确保数据库中的数组大小小于 values 的大小
			{"$expr": bson.M{"$lt": []interface{}{
				bson.M{"$size": "$" + fieldName},
				len(values),
			}}},
		}
	case HasIntersection:
		// 有交集，使用$in表示至少有一个元素匹配
		return []bson.M{{fieldName: bson.M{"$in": values}}}

	case NoIntersection:
		// 无交集
		// 使用 $not 和 $in 确保数据库数组中没有任何元素存在于 values 中
		return []bson.M{{
			"$or": []bson.M{
				{fieldName: bson.M{"$exists": false}},                                    // 字段不存在
				{fieldName: bson.M{"$size": 0}},                                          // 空数组
				{fieldName: bson.M{"$not": bson.M{"$elemMatch": bson.M{"$in": values}}}}, // 所有元素都不在values中
			},
		}}

	case Equal:
		// 相等关系
		if len(s.Values) == 1 {
			return []bson.M{{fieldName: bson.M{"$eq": s.Values[0]}}}
		}
		// 对于数组，需要确保长度相等且包含所有元素
		return []bson.M{{fieldName: bson.M{"$all": values, "$size": len(values)}}}

	default:
		return []bson.M{}
	}
}
